;;;
;;; Place type parent - Inherits from Thing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (place n)
	(let ((type 'place)									;Identifier
			(neighbors '())
		  (super (thing n)))
	(define addNeighbor
		(lambda (direction new-neighbor)
			(if (not (null? (associate direction neighbors)))
				(error "Direction already assigned a neighbor"
					(list (super 'getName) direction))
			)
			(begin (set! neighbors 
					(cons (cons direction new-neighbor) neighbors))
				(display (super 'getName)) (display " : ")
				(display "New neighbor added - ") (display (new-neighbor 'getName))
			)
		)
	)
	(define getNeighbor
		(lambda (direction)
			(let ((p (associate direction neighbors)))
				(if (null? p) nil (cdr p))
			)
		)
	)
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type)				;Return place's type
				  ((eq? msg 'getNeighbors) neighbors)	;Return neighbors
				  ((eq? msg 'addNeighbor) addNeighbor)	;Add new Neighbor
				  ((eq? msg 'getNeighbor) getNeighbor)
				  (else (super msg)))
		)
	)
	this)
)

;;;
;;; Dungeon - Inherits from Place
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (dungeon n)
	(let ((type 'dungeon)
		(rooms '())
		(super (place n)))
	(define addRoom
		(lambda (new-room)
			(set! rooms (cons new-room rooms))
		)
	)
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type)
				  ((eq? msg 'addRoom) addRoom)
				  ((eq? msg 'getRooms) rooms)
				(else (super msg)))
		)
	)
	this)
)

;;;
;;; Town - Inherits from Place
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (town n)
	(let ((type 'town)
		(super (place n)))
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type)
				(else (super msg)))
		)
	)
	this)
)

;;;
;;; Room - Inherits from Place
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (room n)
	(let ((type 'room)
		;(exits '())
		(objects '())
		(super (place n)))
	(define addObject
		(lambda (new-object)
			(set! objects (cons new-object objects))
		)
	)
	(define removeObject
		(lambda (obj)
			(if (not (memq obj objects))
				(error "Object not in room " (list name obj))
			)
			(set! objects (delete obj objects))
		)
	)
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type)
				  ((eq? msg 'addObject) addObject)
				  ((eq? msg 'getObjects) objects)
				  ((eq? msg 'removeObject) removeObject)
				(else (super msg)))
		)
	)
	this)
)

;;;
;;; Building - Inherits from Thing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (building n)
	(let ((type 'building)
		(rooms '())
		(buildings '())
		(super (thing n)))
	(define addRoom
		(lambda (new-room)
			(set! rooms (cons new-room rooms))
		)
	)
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type)
				  ((eq? msg 'addRoom) addRoom)
				  ((eq? msg 'getRooms) rooms)
				(else (super msg)))
		)
	)
	this)
)




;;;
;;; Exit - Inherits from Thing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (exit n p)
	(let ((type 'exit)
		(place p)
		(super (thing n)))
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type)
				(else (super msg)))
		)
	)
	this)
)




;		(north-exit '())
;		(south-exit '())
;		(east-exit '())
;		(west-exit '())
;	(define setExit
;		(lambda (direction new-exit)
;			(cond ((eq? direction 'n) 
;					(set! north-exit new-exit))
;				  ((eq? direction 's) 
;					(set! south-exit new-exit))
;				  ((eq? direction 'e) 
;					(set! east-exit new-exit))
;				  ((eq? direction 'w) 
;					(set! west-exit new-exit))
;				(else (error "Wrong parameter "
;						(list (super 'getName) direction)))
;			)
;		)
;	)
;	(define getExit
;		(lambda (direction)
;			(cond ((eq? direction 'n) north-exit)
;				  ((eq? direction 's) south-exit)
;				  ((eq? direction 'e) east-exit)
;
;				  ((eq? direction 'w) west-exit)
;				(else (error "Wrong parameter "
;						(list (super 'getName) direction)))
;			)
;		)
;	)

;				  ((eq? msg 'setExit) setExit)
;				  ((eq? msg 'getExit) getExit)
